/*
 * FileServer - threaded remoting server that takes generic strings
 * 				from clients and displays them
 *
 * Copyright 2008 James W. Hofmann
 *
 *
 * This code is in the public domain and may be used as-is or for
 * your own programs.
 * 
 */
package basicfiletransfer;

class FileServer
{
	public static var s : neko.net.Socket; 
	
	public static var clients = new List<ClientData>();

	static function listenerClientApi( scnx : haxe.remoting.SocketConnection, server : neko.net.RemotingServer ) 
	{
		trace("connected");
		var c = new ClientData(scnx);
		server.addObject("peer",c);
	}

	static function onClientDisconnected( scnx ) 
	{
		trace("disconnected");
	}

	static function main() 
	{

		var args = neko.Sys.args();
		ClientData.parser = new RequestParser();
		
		switch(args[0])
		{
			default:
				neko.Lib.println("File Server");
				neko.Lib.println("Commands:");
				neko.Lib.println("start <domainname> <port> "+
								"- start listener (default localhost:"+
								"10074)");
			case("start"):	
				var s = new neko.net.ThreadRemotingServer();
				s.initClientApi = listenerClientApi;
				s.clientDisconnected = onClientDisconnected;
				trace("Starting server.");
				var domainname = "localhost";
				var portnum = 10074;
				if(args.length>1)
					domainname = args[1];
				if(args.length>2)
					portnum = Std.parseInt(args[2]);				
				s.run(domainname, portnum);
		}		
		
	}
	
}

class Peer extends haxe.remoting.AsyncProxy<PeerApi> {
}

class ClientData implements PeerApi {

	var peer : Peer;
	var indata : StringBuf;
	var outdata : String;
	var bufferstart : Int;
	var bufferend : Int;

	public static var parser : RequestParser;
	public var complete : Bool;

	public static inline var bytestotransfer = 3000;
	
	public function new( scnx : haxe.remoting.SocketConnection) {
		complete = false;
		peer = new Peer(scnx.FileClient.inst);
		(cast scnx).__private = this;
	}

	public function pull( data : String, lastpart : Bool )
	{
		if (indata==null)
		{
			indata = new StringBuf();
			indata.add(data);
		}
		else
		{
			indata.add(data);
		}
		if (lastpart)
		{
			transactioncomplete();
		}
		else
		{
			peer.push();
		}
	}

	public function push()
	{
		if (bufferend<outdata.length)
		{
			bufferend+=bytestotransfer;
			peer.pull(outdata.substr(bufferstart,bytestotransfer),false);
			bufferstart+=bytestotransfer;
		}
		else
		{
			peer.pull(outdata.substr(bufferstart),true);		
		}
	}
	
	public function uploadrequest(requestcode : Int, requestcontent :
									Dynamic)
	{
		outdata = 
			parser.parse(requestcode, requestcontent);
		beginupload();
	}

	function beginupload()
	{
		bufferstart = 0;
		bufferend = 0;
		push();		
	}

	public function transactioncomplete()
	{
		if (!complete)
		{
			complete = true;
			peer.transactioncomplete();
			neko.Lib.println("finished");
		}
	}
	
	public function downloadrequest(requestcode : Int, requestcontent :
									Dynamic)
	{
		peer.uploadrequest(requestcode, requestcontent);
	}

	public static function 
	ofConnection( scnx : haxe.remoting.SocketConnection ) : ClientData 
	{
		return (cast scnx).__private;
	}

}
